import { Service } from 'egg';
import * as moment from 'moment';
import { OrderedSchedule } from '../model/ordered_schedule';

interface CheckConflictedStudentSchedule {
    id: number;
    date: string;
    time_from: string;
    time_to: string;
    teacher_id: number;
    student_id: number;
}

export default class OrderedScheduleService extends Service {

    public async getByStudent(studentId: number) {
        const result = await this.service.db.orderedSchedule.getOrderedSchedulesByStudent(studentId);
        if (!result) {
            return [];
        }
        return await this.processData(result);
    }

    public async getByTeacher(teacherId: number) {
        const result = await this.service.db.orderedSchedule.getAllByTeacher(teacherId);
        if (!result) {
            return [];
        }
        return await this.processData(result);
    }

    public async getByStudentAndPage(studentId: number, page: number, pageSize: number) {
        const count = await this.service.db.orderedSchedule.getCountByStudent(studentId);
        const result =
            await this.service.db.orderedSchedule.getByStudentAndPage(studentId, page, pageSize);
        if (!result) {
            return [];
        }
        const data = await this.processData(result);
        return {
            data,
            count,
            page,
            pageSize,
        };
    }

    public async getByTeacherAndPage(teacherId: number, page: number, pageSize: number) {
        const count = await this.service.db.orderedSchedule.getCountByStudent(teacherId);
        const result =
            await this.service.db.orderedSchedule.getByTeacherAndPage(teacherId, page, pageSize);
        if (!result) {
            return [];
        }
        const data = await this.processData(result);
        return {
            data,
            count,
            page,
            pageSize,
        };
    }

    public async checkConflict(teacherId: number, studentSchedules: CheckConflictedStudentSchedule[], isStrict = true) {
        const { service } = this;
        let teacherSchedules = await service.db.orderedSchedule.getAllByTeacher(teacherId);
        teacherSchedules = teacherSchedules.map((ts) => ({
            ...ts,
            date: moment(ts.date).format('YYYY-MM-DD'),
            time_from: moment(ts.time_from, 'HH:mm:SS').format('HH:mm'),
            time_to: moment(ts.time_to, 'HH:mm:SS').format('HH:mm'),
        }));
        for (const ss of studentSchedules) {
            const ssDate = moment(ss.date).format('YYYY-MM-DD');
            const ssTimeFrom = moment(ss.time_from, 'HH:mm:SS').format('HH:mm');
            const ssTimeTo = moment(ss.time_to, 'HH:mm:SS').format('HH:mm');
            for (const ts of teacherSchedules) {
                if (ts.date !== ssDate) {
                    continue;
                }
                if (ts.time_from < ssTimeFrom && ts.time_to <= ssTimeFrom) {
                    continue;
                }
                if (ts.time_to > ssTimeTo && ts.time_from >= ssTimeTo) {
                    continue;
                }
                if (isStrict) {
                    if (ts.id === ss.id) {
                        continue;
                    }
                } else {
                    if (ts.student_id === ss.student_id) {
                        continue;
                    }
                }
                return true;
            }
        }
        return false;
    }

    public async updateAll(studentSchedules: any[], conn: any) {
        for await (const ss of studentSchedules) {
            this.service.db.orderedSchedule.update(ss, conn);
        }
    }

    private async processData(schedules: OrderedSchedule[]) {
        const result: any[] = [];
        let currentDate = '';
        let item: any = null;
        const now: any = moment();
        for (const schedule of schedules) {
            const date = moment(schedule.date).format('YYYY-MM-DD');
            if (currentDate !== date) {
                currentDate = date;
                item = {
                    date,
                    schedules: [],
                };
                result.push(item);
            }
            const d: any = moment(date + ' ' + schedule.time_from, 'YYYY-MM-DD HH:mm:SS');
            // 十五分钟内的课程需要老师签到
            const span = d - now;
            let clockStatus = 0; // 不需要签到
            if (span < 0) {
                clockStatus = -1; // 超时
            } else if (span <= 900000) {
                clockStatus = 1; // 需要签到
            }
            const studentName = await this.service.db.user.getUserName(schedule.student_id);
            const teacherName = await this.service.db.user.getUserName(schedule.teacher_id);
            item.schedules.push({
                student_name: studentName,
                teacher_name: teacherName,
                ...schedule,
                time_from: moment(schedule.time_from, 'HH:mm:SS').format('HH:mm'),
                time_to: moment(schedule.time_to, 'HH:mm:SS').format('HH:mm'),
                clock_status: clockStatus,
            });
        }
        return result;
    }
}
